using System;

namespace SharpObjects.Utils
{
    [Serializable]
	public class Integer128
	{
		protected Int64 high;
		protected Int64 low;

		public Integer128()
		{
			this.high = 0;
			this.low = 0;
		}

		public Integer128(Int64 high, Int64 low)
		{
			this.high = high;
			this.low = low;
		}

		public Integer128(byte [] data)
		{
			ParseByteArray(data);
		}

		public Integer128(Guid guid)
		{
			ParseByteArray(guid.ToByteArray());
		}

		protected void ParseByteArray(byte [] data)
		{
			this.high = 0;
			this.low = 0;

			for(int k = 0; k < data.Length; k++)
			{
				if(k < 8)
				{
					this.low = this.low | (((Int64)data[k]) << (8 * k));
				}
				else
				{
					this.high = this.high | (((Int64)data[k]) << (8 * (k - 8)));
				}
			}		
		}


		public Int64 High { get { return this.high; } set { this.high = value; } }
		public Int64 Low { get { return this.low; } set { this.low = value; } }

		public static bool operator == (Integer128 i1, Integer128 i2)
		{
			return i1.high == i2.high && i1.low == i2.low;
		}

		public static bool operator != (Integer128 i1, Integer128 i2)
		{
			return i1.high != i2.high || i1.low != i2.low;
		}

		public override int GetHashCode()
		{
            return (high.ToString() + low.ToString()).GetHashCode();
		}

		public override bool Equals(object obj)
		{
			Integer128 i = (Integer128)obj;
			return this.high == i.high && this.low == i.low;
		}

		public override string ToString()
		{
			return string.Format("{0, 16:x16}{1, 16:x16}", this.high, this.low);
		}

        public static bool operator <(Integer128 i1, Integer128 i2)
        {
            Int64 high = i1.high - i2.high;

            if (high == 0)
            {
                return i1.low < i2.low;
            }
            else
            {
                return high < 0;
            }
        }

        public static bool operator <=(Integer128 i1, Integer128 i2)
        {
            Int64 high = i1.high - i2.high;

            if (high == 0)
            {
                return i1.low <= i2.low;
            }
            else
            {
                return high < 0;
            }
        }

        public static bool operator >(Integer128 i1, Integer128 i2)
        {
            Int64 high = i1.high - i2.high;

            if (high == 0)
            {
                return i1.low > i2.low;
            }
            else
            {
                return high > 0;
            }
        }

        public static bool operator >=(Integer128 i1, Integer128 i2)
        {
            Int64 high = i1.high - i2.high;

            if (high == 0)
            {
                return i1.low >= i2.low;
            }
            else
            {
                return high > 0;
            }
        }

	}
}
